import otherHelpers from "./others";
import autoDisposeWhenUnload from "./autoDisposeWhenUnload";

const nativeWin = otherHelpers.globalWin;

const instanceList = [];
const dataList = [];
let currentIndex = -1;

autoDisposeWhenUnload(function () {
    instanceList.forEach(w => w?.destroy());
    instanceList.splice(0, instanceList.length);
    dataList.splice(0, dataList.length);
});

export default class URLHelper {
    constructor(url = nativeWin?.location.href) {
        instanceList.push(this);
        dataList.push({
            url: url || '',
            search: null,
            hash: null,
            serverPath: null,
        });
    }

    get search() {
        const data = dataList[instanceList.indexOf(this)];
        if (null === data.search) {
            const url = this.serverPath;
            const qIndex = url.indexOf('?');
            const res = {};
            if (qIndex > -1) {
                return url.slice(1 + qIndex).split('&').reduce((res, item) => {
                    const equalIndex = item.indexOf('=');
                    if (-1 < equalIndex) {
                        res[item.slice(0, equalIndex)] = item.slice(1 + equalIndex);
                    } else {
                        res[item] = '';
                    }
                    return res;
                }, res);
            }
            data.search = res;
        }
        return data.search;
    }

    set search(s) {
        const data = dataList[instanceList.indexOf(this)];
        const url = data.url;
        const sharpIndex = url.indexOf('#');
        const qIndex = this.serverPath.indexOf('?');
        const hash = this.hash;
        let prevPart;
        if (-1 === qIndex) {
            if (-1 === sharpIndex) {
                prevPart = url;
            } else {
                prevPart = url.slice(0, sharpIndex);
            }
        } else {
            prevPart = url.slice(0, qIndex);
        }
        data.url = prevPart + '?' + Object.keys(s).map(k => `${k}=${s[k] ?? ''}`).join('&') + hash;
        data.search = null;
    }

    get hash() {
        const data = dataList[instanceList.indexOf(this)];
        if (null === data.hash) {
            const url = data.url;
            const sharpIndex = url.indexOf('#');
            data.hash = -1 === sharpIndex ? '' : url.slice(sharpIndex);
        }
        return data.hash;
    }

    get serverPath() {
        const data = dataList[instanceList.indexOf(this)];
        if (null === data.serverPath) {
            const url = data.url;
            const sharpIndex = url.indexOf('#');
            data.serverPath = -1 === sharpIndex ? url : url.slice(0, sharpIndex);
        }
        return data.serverPath;
    }

    clone() {
        return new URLHelper(dataList[instanceList.indexOf(this)].url);
    }

    toString() {
        return dataList[instanceList.indexOf(this)].url;
    }

    destroy() {
        const index = instanceList.indexOf(this);
        if (index === currentIndex) {
            currentIndex = -1;
        }
        instanceList[index] = null;
        dataList[index] = null;
    }

    static get current() {
        if (-1 === currentIndex) {
            const helper = new URLHelper();
            currentIndex = instanceList.indexOf(helper);
        }
        return instanceList[currentIndex];
    }

    static from(url) {
        return new URLHelper(url);
    }
}
